package services

import (
	"errors"
	"fmt"
	"longmen/server/config/global"
	"longmen/server/pkg/common/helper/const"
	string2 "longmen/server/pkg/common/helper/string"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql"
	"longmen/server/pkg/db/mysql/db_live"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_live"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/db/redis/cache"
	"time"

	"github.com/jinzhu/copier"
	"longmen/server/pkg/common/api_models"
)

func (s *Service) AttentAnchors(req *api_models.AttentanchorsReq, user *models_main.User) (int, error) {
	fName := "AttentAnchors"
	lives, err := db_live.GetLivesParam(map[string]interface{}{"anchorid": map[string]interface{}{"in": req.Anchorids}}, "", 0, 10)
	if err != nil {
		return 0, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	if len(lives) == 0 {
		return 0, fmt.Errorf("%s%s", util.Convert(fName), "列表中没有在线的主播")
	}
	attents := make([]*models_main.AnchorFans, 0)
	for _, live := range lives {
		attents = append(attents, &models_main.AnchorFans{
			Anchorid:   live.Anchorid,
			Fansid:     user.Id,
			LiveId:     live.Liveid,
			CreateTime: time.Now(),
		})
	}
	successList, err := db_main.ClauseInsertAnchorsFans(attents)
	if err != nil {
		return 0, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}

	err = cache.OnTaskEvent(int(user.Id), _const.TASK_DAILY_SUB_ANCHOR, len(attents)) //一次关注多个主播
	if err != nil {
		global.Log.Infof("任务:推送关注事件失败，用户%d，活动ID:%d", user.Id, int(_const.TASK_DAILY_SUB_ANCHOR), err.Error())
	}

	attentids := cache.GetUserAttentAnchorIds(user.Id) //更新redis缓存
	for _, r := range attents {
		if string2.IntIsInSlice(attentids, r.Anchorid) {
			attentids = util.DiffArrayInt(attentids, r.Anchorid)
		}
		fansCount, err := db_main.GetFansCount(map[string]interface{}{"anchorid": r.Anchorid})
		if err == nil {
			cache.SetFansCount(r.Anchorid, fansCount)
		}

	}
	cache.SetUserAttentAnchorIds(user.Id, attentids)

	return len(successList), nil
}

func (s *Service) AttentAnchor(r *api_models.AttentanchorReq, user *models_main.User) (string, *api_models.AttentanchorResp, error) {
	fName := "AttentAnchor"
	anchor, err := cache.GetUserFullInfo(r.Anchorid)
	if err != nil {
		return global.Lang.T("follow_failed"), nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	if anchor.IsAnchor != 1 {
		return global.Lang.T("follow_failed"), nil, errors.New(global.Lang.T("follow_failed"))
	}
	action_type := 0
	attent, err := db_main.GetAnchorFansParam(map[string]interface{}{"fansid": user.Id, "anchorid": r.Anchorid})
	if err != nil {
		return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	if attent.Id > 0 { //粉丝在列表里AnchorFans
		if cache.AddFollowCounter(user.Id, r.Anchorid) > _const.FOLLOW_LIMIT_TIME {
			return global.Lang.T("too_many_repetitions"), nil, errors.New(global.Lang.T("too_many_repetitions"))
		}
		err = db_main.DeleteAnchorFans(attent) //取消关注
		if err != nil {
			return global.Lang.T("network_timeout"), nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
		}
		attentids := cache.GetUserAttentAnchorIds(user.Id) //更新redis缓存
		if string2.IntIsInSlice(attentids, r.Anchorid) {
			attentids = util.DiffArrayInt(attentids, r.Anchorid)
		}
		cache.SetUserAttentAnchorIds(user.Id, attentids)
		fansCount, err := db_main.GetFansCount(map[string]interface{}{"anchorid": r.Anchorid})
		if err != nil {
			return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
		}
		cache.SetFansCount(r.Anchorid, fansCount)
		return "", &api_models.AttentanchorResp{FansCount: fansCount, Type: action_type}, nil
	} else { //关注
		if cache.AddFollowCounter(user.Id, r.Anchorid) > _const.FOLLOW_LIMIT_TIME {
			return global.Lang.T("too_many_repetitions"), nil, errors.New(global.Lang.T("too_many_repetitions"))
		}
		liveInfo, err := db_live.GetLiveParam(map[string]interface{}{"anchorid": r.Anchorid}) //直播中的主播入库时加上live_id
		if err != nil {
			return "", nil, fmt.Errorf("%s%s", util.Convert2(), err.Error())
		}
		attent = &models_main.AnchorFans{Fansid: user.Id, Anchorid: r.Anchorid, CreateTime: time.Now(), LiveId: liveInfo.Liveid}
		err = db_main.InsertAnchorFans(attent) //关注
		if err != nil {
			return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
		}
		//更新redis缓存
		attentids := cache.GetUserAttentAnchorIds(user.Id)
		if !string2.IntIsInSlice(attentids, r.Anchorid) {
			attentids = append(attentids, r.Anchorid)
		}
		cache.SetUserAttentAnchorIds(user.Id, attentids)
		fansCount, err := db_main.GetFansCount(map[string]interface{}{"anchorid": r.Anchorid})
		if err != nil {
			return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
		}
		cache.SetFansCount(r.Anchorid, fansCount)
		pubData := &api_models.PubAttentanchorMess{UserId: user.Id, Anchorid: r.Anchorid, RoomId: r.Anchorid}
		_ = cache.AttentAnchorChannel(pubData)
		action_type = 1
		err = cache.OnTaskEvent(user.Id, _const.TASK_DAILY_SUB_ANCHOR, 1)
		if err != nil {
			global.Log.Infof("任务：用户%d关注主播事件推送失败TaskId%d", user.Id, int(_const.TASK_DAILY_SUB_ANCHOR), err.Error())
		}
		return "", &api_models.AttentanchorResp{FansCount: fansCount, Type: action_type}, nil
	}
}

func (s *Service) CheckAnchorExist(r *api_models.CheckAnchorExistReq) error {
	anchor, err := cache.GetUserFullInfo(r.Anchorid)
	if err != nil {
		return err
	}
	if anchor.IsAnchor != 1 && anchor.Status != 0 {
		return errors.New("Anchor not exists")
	}
	return nil
}

func (s *Service) GetAnchorInfo(r *api_models.GetAnchorInfoReq, user *models_main.User) (string, *api_models.GetAnchorInfoResp, error) {
	fName := "GetAnchorInfo"
	anchor, err := cache.GetUserFullInfo(r.Anchorid)
	if err != nil {
		return "", nil, err
	}
	if anchor.Status != 0 {
		return "", nil, errors.New("Anchor status abnormal")
	}
	profile, err := db_main.GetUserProfileParam(map[string]interface{}{"uid": r.Anchorid})
	if err != nil {
		return "", nil, err
	}
	live, err := db_live.GetLiveParam(map[string]interface{}{"anchorid": r.Anchorid})
	if err != nil {
		return "", nil, err
	}

	if user != nil {
		//写入访客记录
		visitorlog := &models_main.VisitorLog{
			Uid:        r.Anchorid,
			Visitorid:  user.Id,
			CreateTime: time.Now(),
		}
		err = db_main.InsertVisitorLog(visitorlog)
		if err == nil {
			visitorCount, err := db_main.GetVisitorLogCount(map[string]interface{}{"uid": r.Anchorid})
			if err == nil {
				cache.SetVisitorCount(r.Anchorid, visitorCount)
			}
		}
	}

	resp := &api_models.GetAnchorInfoResp{}
	err = copier.Copy(resp, anchor)
	if err != nil {
		return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	resp.Profile = profile
	resp.Live = live
	if r.Uid > 0 {
		//查询是否已关注
		checkAttent, err := db_main.GetAnchorFansParam(map[string]interface{}{"anchorid": r.Anchorid, "fansid": r.Uid})
		if err != nil {
			return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
		}
		if checkAttent.Id > 0 {
			resp.Isattent = 1
		}
	}
	//关注数量
	resp.AttentCount = len(cache.GetUserAttentAnchorIds(r.Anchorid))
	//粉丝数量
	resp.FansCount = cache.GetFansCount(r.Anchorid)
	//送礼数量
	resp.GiftSpend = cache.GetSendGiftCount(r.Anchorid)
	//动态数量
	resp.MomentCount = 0

	return "", resp, nil
}

func (s *Service) CheckAttent(r *api_models.CheckAttentReq, user *models_main.User) (*models_main.AnchorFans, error) {
	return db_main.GetAnchorFansParam(map[string]interface{}{"fansid": user.Id, "anchorid": r.Anchorid})
}

func (s *Service) GetAnchorBasicInfo(r *api_models.GetAnchorBasicInfoReq) (string, *api_models.GetAnchorBasicInfoResp, error) {
	fName := "Getanchorbasicinfo"
	
	user, err := cache.GetUserFullInfo(r.Anchorid)
	if err != nil {
		return "", nil, err
	}
	if user.Status != 0 {
		return "", nil, errors.New("Anchor status abnormal")
	}

	resp := &api_models.GetAnchorBasicInfoResp{}
	err = copier.Copy(resp, user)
	if err != nil {
		return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	profile, err := db_main.GetUserProfileParam(map[string]interface{}{"uid": user.Id})
	if err != nil {
		return "", nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	resp.Profile = *profile

	//粉丝数量
	resp.FansCount = cache.GetFansCount(r.Anchorid)
	resp.Popularity = 0 //user.DiamondTotal*88 + user.AnchorPoint

	return "", resp, nil
}

func (s *Service) AddVisitorLog(r *api_models.AddVisitorLogReq, user *models_main.User) error {
	fName := "AddVisitorLog"
	if user == nil {
		return errors.New("user is nil")
	}
	visitorlog := &models_main.VisitorLog{
		Uid:        r.Anchorid,
		Visitorid:  user.Id,
		CreateTime: time.Now(),
	}
	if err := db_main.InsertVisitorLog(visitorlog); err != nil {
		return fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	visitorCount, err := db_main.GetVisitorLogCount(map[string]interface{}{"uid": r.Anchorid})
	if err != nil {
		return fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	cache.SetVisitorCount(r.Anchorid, visitorCount)
	return nil
}

func (s *Service) GetAttentAnchors(r *api_models.GetAttentAnchorsReq, user *models_main.User) (*api_models.GetAttentAnchorsResp, error) {
	fName := "GetAttentAnchors"
	attents, err := db_main.GetAnchorFanssParam(map[string]interface{}{"fansid": user.Id}, "create_time desc", r.Page, r.Size)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	count, err := db_main.GetFansCount(map[string]interface{}{"fansid": user.Id})
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	resp := &api_models.GetAttentAnchorsResp{}
	resp.TotalCount = count
	err = copier.Copy(&resp.List, &attents)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	anchorids := make([]int, 0)
	for idx := range attents {
		anchorids = append(anchorids, attents[idx].Anchorid)
	}
	anchorMap, err := s.GetAnchors(0, anchorids, "", 0, 0)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}

	lives, err := db_live.GetLivesParam(map[string]interface{}{"anchorid": map[string]interface{}{"in": anchorids}}, "", 0, 0)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}
	liveMap := make(map[int]*models_live.Live)
	for idx := range lives {
		liveMap[lives[idx].Anchorid] = lives[idx]
	}
	for idx := range resp.List {
		if _, ok := anchorMap[resp.List[idx].Anchorid]; ok {
			resp.List[idx].Anchor.Anchor = *anchorMap[resp.List[idx].Anchorid]
			resp.List[idx].Anchor.Isattent = 1
		}
		if _, ok := liveMap[resp.List[idx].Anchorid]; ok {
			resp.List[idx].Anchor.Live = liveMap[resp.List[idx].Anchorid]
		}
	}
	return resp, nil
}

func (s *Service) GetAnchors(guildid int, ids []int, order string, page, size int) (map[int]*api_models.Anchor, error) {
	fName := "GetAnchor"
	var err error
	result := make([]*api_models.Anchor, 0)
	partUsers := make([]*models_main.PartUser, 0)

	if guildid > 0 {
		partUsers, err = db_main.GetPartUsersParam(map[string]interface{}{"guildid": guildid}, order, page, size)
	} else if len(ids) > 0 {
		partUsers, err = db_main.GetPartUsersParam(map[string]interface{}{"id": map[string]interface{}{"in": ids}}, "", 0, 0)
	} else {
		partUsers, err = db_main.GetPartUsersParam(map[string]interface{}{"is_anchor": 1}, order, page, size)
	}
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}

	err = copier.Copy(&result, &partUsers)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}

	for _, v := range result {
		v.FansNum = cache.GetFansCount(v.Id)
	}
	resultMap := make(map[int]*api_models.Anchor)
	for idx := range result {
		resultMap[result[idx].Id] = result[idx]
	}

	return resultMap, nil
}

func (s *Service) GetAnchor(id int) (*api_models.Anchor, error) {
	fName := "GetAnchor"
	anchors, err := s.GetAnchors(0, []int{id}, "", 0, 0)
	if err != nil {
		return nil, fmt.Errorf("%s%s", util.Convert(fName), err.Error())
	}

	if len(anchors) > 0 {
		return anchors[id], nil
	}
	return &api_models.Anchor{}, nil
}

func (s *Service) GetTags(ids []int64) ([]*models_main.ConfigTag, error) {
	var (
		err      error
		fName    = "GetTags"
		tagQuery []*models_main.ConfigTag
	)

	if tagQuery, err = mysql.GetConfigTagByIds2(ids); err != nil {
		return nil, fmt.Errorf("%s %s", util.Convert(fName), err.Error())
	}

	if len(tagQuery) > 0 {
		return tagQuery, nil
	}

	return make([]*models_main.ConfigTag, 0), nil
}
